home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1997 / MacHack 1997.toast / Hacks / Hacks ’96 / FontMancer / Common / Display.c < prev    next >
Text File  |  1996-06-21  |  9KB  |  328 lines

  1. /***********************************************************************
  2. #
  3. #        displays.c
  4. #
  5. #        This segment handles the Display Manager notification and
  6. #        repositions application windows in response.
  7. #
  8. #        Author: Michael Marinkovich
  9. #                Apple Developer Technical Support
  10. #
  11. #
  12. #        Modification History: 
  13. #
  14. #            10/12/95    MWM     Initial coding
  15. #            4/22/96        WCS        Tweaked it for use in my program.
  16. #                                DO NOT USE in your code, refer to
  17. #                                develop issue 18 or Apple's web
  18. #                                site for original code.
  19. #
  20. #
  21. #        Copyright © 1992-95 Apple Computer, Inc., All Rights Reserved
  22. #
  23. #
  24. ***********************************************************************/
  25.  
  26. #include "Display.h"
  27.  
  28. extern WindowPtr gMainWindow;
  29.  
  30. //----------------------------------------------------------------------
  31. //
  32. //    InstallAEDMNotification - tell DM that we want to be notified by AE.
  33. //                      
  34. //                      
  35. //----------------------------------------------------------------------
  36.  
  37. OSErr InstallAEDMNotification(void)
  38. {
  39.     OSErr        err;
  40.     
  41.     err = AEInstallEventHandler(kCoreEventClass, kAESystemConfigNotice,
  42.                                 NewAEEventHandlerProc(DoAEDisplayUpdate),
  43.                                 0L, false);
  44.  
  45.     return err;
  46.  
  47. }
  48.  
  49. //----------------------------------------------------------------------
  50. //
  51. //    DoAEDisplayUpdate - Display Manager calls this proc when a depth or  
  52. //                        mode change is made. Your application should
  53. //                        handle window repositioning here. 
  54. //----------------------------------------------------------------------
  55.  
  56. pascal OSErr DoAEDisplayUpdate(AppleEvent *event,AppleEvent *reply,long refCon)
  57. {
  58.     OSErr                    err;
  59.  
  60.     err = HandleNotification(event);
  61.  
  62.     return noErr;
  63.     
  64. }
  65.  
  66.  
  67. //----------------------------------------------------------------------
  68. //
  69. //    HandleNotification - handle the AppleEvent returned by either the 
  70. //                           callback or the AppleEvent procedure.
  71. //                      
  72. //----------------------------------------------------------------------
  73.  
  74. OSErr HandleNotification(AppleEvent *event)
  75. {
  76.     OSErr                    err;
  77.     GrafPtr                    oldPort;
  78.     AEDescList                displayList;
  79.     AEDescList                aDisplay;
  80.     AERecord                oldConfig,newConfig;
  81.     AEKeyword                tempWord;
  82.     DisplayIDType            displayID;
  83.     unsigned long            returnType;
  84.     long                    count;
  85.     Rect                    oldRect, newRect;
  86.     GDHandle                gd;
  87.     
  88.     GetPort(&oldPort);
  89.  
  90.     // Get a list of the displays from the Display Notice AppleEvent.
  91.     err = AEGetParamDesc(event,kAEDisplayNotice,typeWildCard,&displayList);
  92.     // How many items in the list
  93.     err = AECountItems(&displayList,&count);
  94.     
  95.     while (count > 0) {     // Loop through the list.
  96.         err = AEGetNthDesc(&displayList, count, typeWildCard, &tempWord, 
  97.                                     &aDisplay);
  98.         
  99.         // Get the Old Rect.            
  100.         err = AEGetNthDesc(&aDisplay, 1, typeWildCard, &tempWord, 
  101.                            &oldConfig);
  102.         err = AEGetKeyPtr(&oldConfig, keyDeviceRect, typeWildCard, 
  103.                           &returnType, &oldRect, 8, nil);
  104.         
  105.         // Get the DisplayID so we can get the GDevice later.                
  106.         err = AEGetKeyPtr(&oldConfig, keyDisplayID, typeWildCard, 
  107.                           &returnType, &displayID, 8, nil);
  108.  
  109.         // Get the New Rect.                
  110.         err = AEGetNthDesc(&aDisplay, 2, typeWildCard, &tempWord, 
  111.                            &newConfig);
  112.         err = AEGetKeyPtr(&newConfig, keyDeviceRect, typeWildCard, 
  113.                           &returnType, &newRect, 8, nil);
  114.         
  115.         // If the New and Old rects are not the same then we can assume
  116.         // the GDevice has changed and we need to rearrange the windows.
  117.         if (err == noErr && !EqualRect(&newRect, &oldRect)) {
  118.             err = DMGetGDeviceByDisplayID((DisplayIDType) displayID, &gd, false);
  119.             HandleDeviceChange(gd, &newRect);
  120.         }
  121.         
  122.         count--;
  123.         err = AEDisposeDesc(&aDisplay);
  124.         err = AEDisposeDesc(&oldConfig);
  125.         err = AEDisposeDesc(&newConfig);
  126.  
  127.     }
  128.     
  129.     err = AEDisposeDesc(&displayList);
  130.     SetPort(oldPort);
  131.     
  132.     return err;
  133. }
  134.  
  135.  
  136. //----------------------------------------------------------------------
  137. //
  138. //    HandleDeviceChange - called when the oldconfig is different from 
  139. //                         newconfig. Will check all windows on effected 
  140. //                           device and move if needed.
  141. //----------------------------------------------------------------------
  142.  
  143. OSErr HandleDeviceChange(GDHandle gd, Rect *newRect)
  144. {
  145.     OSErr        err = noErr;
  146.     //GDHandle    gd;
  147.     GDHandle    onGD;
  148.     WindowRef    window;
  149.     
  150.     // Get the GDevice from the DisplayID.
  151.     //err = DMGetGDeviceByDisplayID((DisplayIDType) displayID, &gd, false);
  152.  
  153.     //if (err == noErr && gd != nil) {
  154.         window = gMainWindow;
  155.         
  156.         SetPort(window); 
  157.         // which device holds the greatest portion of the window
  158.         onGD = GetGreatestDevice(window);
  159.         
  160.         // If the window is not 50% or greater on
  161.         // the desired device then pass it up.
  162.         if (onGD == gd)
  163.             if (OutOfBoundsRect(gd, window, *newRect))
  164.                 MoveInbounds(window, gd, *newRect);
  165.     //}
  166.     return err;
  167.     
  168. }
  169.  
  170.     
  171. //----------------------------------------------------------------------
  172. //
  173. //    OutOfBoundsRect -  check to see if the window is out of the device
  174. //                       rect.
  175. //                      
  176. //----------------------------------------------------------------------
  177.  
  178. Boolean OutOfBoundsRect(GDHandle gd, WindowRef window, Rect screenRect)
  179. {
  180.     Boolean        out = false;
  181.     Rect        windRect;
  182.     short        mHeight = 0;
  183.     
  184.     GetWindowRect(window, &windRect);
  185.     
  186.     if (gd == GetMainDevice())
  187.         mHeight = GetMBarHeight();
  188.  
  189.     if ((windRect.right > screenRect.right) || (windRect.bottom > screenRect.bottom))
  190.         out = true;
  191.  
  192.     if ((windRect.left < screenRect.left) || (windRect.top < screenRect.top + mHeight))
  193.         out = true;
  194.     
  195.     return out;
  196.     
  197. }
  198.     
  199.     
  200. //----------------------------------------------------------------------
  201. //
  202. //    MoveInbounds -  Move window on to desired device
  203. //                        
  204. //                      
  205. //----------------------------------------------------------------------
  206.  
  207. void MoveInbounds(WindowRef window, GDHandle gd, Rect screenRect)
  208. {
  209.     Rect        bounds;
  210.     short        mHeight = 0;
  211.     short        hGlobal;
  212.     short        vGlobal;
  213.         
  214.     GetWindowRect(window, &bounds);
  215.  
  216.     if (gd == GetMainDevice())
  217.         mHeight = GetMBarHeight();
  218.         
  219.     hGlobal = bounds.left;
  220.     vGlobal = bounds.top + kTitleBarHeight;
  221.     
  222.     // we want to make the left-top a priority so adjust it first
  223.     // as to override the bottom, right movements. This is so we
  224.     // can resize the window later. 
  225.     
  226.     if (((bounds.right - bounds.left) > (screenRect.right - screenRect.left)) ||
  227.         ((bounds.bottom - bounds.top) > 
  228.         ((screenRect.bottom - screenRect.top) - mHeight))) {
  229.         
  230.         // adjust left
  231.         if (bounds.left < screenRect.left)
  232.             hGlobal = screenRect.left + kFudgeFactor;
  233.         
  234.         // adjust top
  235.         if (bounds.top < screenRect.top + mHeight)
  236.             vGlobal = screenRect.top + kTitleBarHeight + mHeight + kFudgeFactor;
  237.  
  238.     }    
  239.     else {
  240.         // adjust left
  241.         if (bounds.left < screenRect.left)
  242.             hGlobal = screenRect.left + kFudgeFactor;
  243.         else {
  244.             // adjust right
  245.             if (bounds.right > screenRect.right)
  246.                 hGlobal = (screenRect.right - (bounds.right - bounds.left)) - kFudgeFactor;
  247.         }
  248.         
  249.         // adjust top
  250.         if (bounds.top < screenRect.top + mHeight)
  251.             vGlobal = screenRect.top + kTitleBarHeight + mHeight + kFudgeFactor;
  252.  
  253.         else {
  254.             // adjust bottom
  255.             if (bounds.bottom > screenRect.bottom)
  256.                 vGlobal = (screenRect.bottom -  kFudgeFactor -
  257.                           (bounds.bottom - bounds.top) + mHeight);
  258.         }        
  259.  
  260.     }
  261.     
  262.     MoveWindow(window, hGlobal, vGlobal,false);
  263.         
  264. }
  265.     
  266.  
  267. //----------------------------------------------------------------------
  268. //
  269. //    GetGreatestDevice - find thw device that holds the greatest area 
  270. //                        of the window.
  271. //                      
  272. //----------------------------------------------------------------------
  273.  
  274. GDHandle GetGreatestDevice(WindowRef window)
  275. {
  276.     GDHandle    gd;
  277.     GDHandle    savedGD;
  278.     Rect        gdRect;
  279.     Rect        foundRect;
  280.     long        size;
  281.     long        greatest = nil;
  282.  
  283.     gd = DMGetFirstScreenDevice(dmOnlyActiveDisplays);
  284.     savedGD = gd;
  285.     
  286.     // Loop through the device list
  287.     while (gd != nil) {    
  288.         gdRect = (**gd).gdRect;
  289.         
  290.         GlobalToLocal(&topLeft(gdRect));
  291.         GlobalToLocal(&botRight(gdRect));
  292.         
  293.         if (SectRect(&window->portRect, &gdRect, &foundRect)) {
  294.             size = ((long)(foundRect.right - foundRect.left) * 
  295.                    (long)(foundRect.bottom - foundRect.top));
  296.             
  297.             if (size > greatest) {
  298.                 greatest = size;
  299.                 savedGD = gd;        // save the greatest device
  300.             }    
  301.         }
  302.         gd = DMGetNextScreenDevice(gd, dmOnlyActiveDisplays);
  303.     }
  304.     
  305.     return savedGD;
  306. }
  307.  
  308.  
  309. //----------------------------------------------------------------------
  310. //
  311. //    GetWindowRect - return actual window rect in global coords
  312. //                    
  313. //                    
  314. //----------------------------------------------------------------------
  315.  
  316. void GetWindowRect(WindowRef window, Rect *windRect)
  317. {    
  318.     *windRect = window->portRect;
  319.     
  320.     // add the titlebar height for actual height
  321.     windRect->top -= kTitleBarHeight;
  322.     
  323.     LocalToGlobal(&TopLeft(*windRect));
  324.     LocalToGlobal(&BotRight(*windRect));
  325.  
  326.  
  327. }
  328.